package orm

// 封装crud 不提供list方法， 尽量还是构建一下service层这样可以方便的重写这些增删改查
// 当这些方法不满足需求时可以在service子类中重写

// GetIds 获取结构体切片中的ids列表
func GetIds[T GetId](req []T) []uint {
	ids := make([]uint, 0, len(req))
	for _, v := range req {
		ids = append(ids, v.GetId())
	}
	return ids
}

// FindByIds 根据Ids获取对象
func FindByIds[T any](ids []uint) ([]T, error) {
	var data []T
	if err := GetDb().Where("id in ?", ids).Find(&data).Error; err != nil {
		return nil, err
	}
	return data, nil
}

type GetId interface {
	GetId() uint
}

// AppendData 根据结构体中的id重新填充数据不会保证顺序
func AppendData[T GetId](req []T) ([]T, error) {
	ids := GetIds[T](req)
	return FindByIds[T](ids)
}

func Create[T any](req T) error {
	return GetDb().Create(&req).Error
}

func Delete[T any](id uint) error {
	var modelInfo T
	return GetDb().Where("id = ?", id).Delete(&modelInfo).Error
}

func BatchUpdate[T any](newData any, ids uint) error {
	var oldData T
	return GetDb().Model(&oldData).Where("id in ?", ids).Updates(&newData).Error
}

func Update[T any](newData T, id uint, preload ...string) error {
	var oldData T

	oldDb := GetDb().Where("id = ?", id)
	for _, v := range preload {
		oldDb.Preload(v)
	}
	if err := oldDb.First(&oldData).Error; err != nil {
		return err
	}

	//删除旧的关联
	for _, v := range preload {
		if err := GetDb().Model(&oldData).Association(v).Clear(); err != nil {
			return err
		}
	}

	//保存
	if err := GetDb().Where("id = ?", id).
		Updates(&newData).Error; err != nil {
		return err
	}
	return nil
}

func Detail[T any](id int, preload ...string) (data T, err error) {
	db := GetDb().Where("id = ?", id)
	for _, v := range preload {
		db.Preload(v)
	}
	err = db.First(&data).Error
	return
}
